package cn.agiledata.bank.transaction.logic;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 批量交易的交易对方
 * 
 * @author maxianbo
 * 
 */
public final class BatchPeerAccount {
    /**
     * 交易对方账户类型：支付账户
     */
    private static final int TYPE_INNER = 0;

    /**
     * 交易对方账户类型：银行账户
     */
    private static final int TYPE_BANK = 1;

    /**
     * 创建一个交易对象账户类型为银行账户的批量交易交易对方对象
     */
    public static BatchPeerAccount getBankBatchPeerAccount() {
        return new BatchPeerAccount(TYPE_BANK);
    }

    /**
     * 创建一个交易对象账户类型为支付账户的批量交易交易对方对象
     */
    public static BatchPeerAccount getInnerBatchPeerAccount() {
        return new BatchPeerAccount(TYPE_INNER);
    }

    /**
     * 交易对方账户金额设置清单
     */
    private Map values;

    /**
     * 交易对方账户类型
     */
    private int type;

    private BatchPeerAccount(int kind) {
        this.values = new HashMap();
        this.type = kind;
    }

    /**
     * 清除所有交易对方金额设置
     */
    public void clear() {
        this.values.clear();
    }

    /**
     * 判断是否包含指定交易对方账户id的金额设置
     * 
     * @param peerAccountId
     *            交易对方账户id
     * @return true if 包含指定交易对方账户id的金额设置, otherwise false
     */
    public boolean contains(long peerAccountId) {
        return this.values.containsKey(getKey(peerAccountId));
    }

    /**
     * 获取指定交易对方账户id的金额设置
     * 
     * @param peerAccountId
     *            交易对方账户id
     * @return 指定交易对方账户id的金额设置
     */
    public PeerAccountAmount get(long peerAccountId) {
        return (PeerAccountAmount) this.values.get(getKey(peerAccountId));
    }

    /**
     * 
     * @return 笔数
     */
    public int getCount() {
        return this.values.size();
    }

    /**
     * 根据交易对方账户id获取保存到内部map中使用的关键字
     * 
     * @param peerAccountId
     *            交易对方账户id
     * @return 保存到内部map中使用的关键字
     */
    private Object getKey(long peerAccountId) {
        return new Long(peerAccountId);
    }

    /**
     * 
     * @return 计手续费的总金额
     */
    public BigDecimal getTotalAmountWithFee() {
        // 不通过调用已有方法实现，这样只需要遍历一次，否则需要遍历两次
        double total = 0.0d;
        for (Iterator it = this.values.entrySet().iterator(); it.hasNext();) {
            Map.Entry entry = (Map.Entry) it.next();
            PeerAccountAmount p = (PeerAccountAmount) entry.getValue();
            total += (p.getAmount().doubleValue() + p.getFee().doubleValue());
        }
        return new BigDecimal(total).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 
     * @return 不计手续费的总金额
     */
    public BigDecimal getTotalAmountWithoutFee() {
        double total = 0.0d;
        for (Iterator it = this.values.entrySet().iterator(); it.hasNext();) {
            Map.Entry entry = (Map.Entry) it.next();
            PeerAccountAmount p = (PeerAccountAmount) entry.getValue();
            total += p.getAmount().doubleValue();
        }
        return new BigDecimal(total);
    }

    /**
     * 
     * @return 总手续费
     */
    public BigDecimal getTotalFee() {
        double total = 0.0d;
        for (Iterator it = this.values.entrySet().iterator(); it.hasNext();) {
            Map.Entry entry = (Map.Entry) it.next();
            PeerAccountAmount p = (PeerAccountAmount) entry.getValue();
            total += p.getFee().doubleValue();
        }
        return new BigDecimal(total);
    }

    /**
     * 
     * @return 所有交易对方金额清单
     */
    public PeerAccountAmount[] getValues() {
        return (PeerAccountAmount[]) this.values.values().toArray(
                new PeerAccountAmount[0]);
    }

    /**
     * 判断交易对方账户类型是否银行账户
     * 
     * @return true if 交易对方账户类型是银行账户, otherwise false
     */
    public boolean isBankBatchPeerAccount() {
        return this.type == TYPE_BANK;
    }

    /**
     * 判断交易对方账户类型是否支付账户
     * 
     * @return true if 交易对方账户类型是支付账户, otherwise false
     */
    public boolean isInnerBatchPeerAccount() {
        return this.type == TYPE_INNER;
    }

    /**
     * 将指定交易对方账户id、金额和手续费加入交易对方金额清单中，如果清单中已有该交易对方账户id，则原有设置将被覆盖
     * 
     * @param peerAccountId
     *            交易对方账户id
     * @param amount
     *            金额
     * @param fee
     *            手续费
     * @return 新的交易对方金额
     */
    public PeerAccountAmount put(long peerAccountId, BigDecimal amount,
            BigDecimal fee) {
        PeerAccountAmount p = new PeerAccountAmount(peerAccountId);
        p.setAmount(amount);
        p.setFee(fee);
        this.values.put(getKey(peerAccountId), p);
        return p;
    }

    /**
     * 设置指定交易对方账户id的订单编号
     * 
     * @param peerAccountId
     *            交易对方账户id
     * @param orderId
     *            订单编号
     * @return 修改后的交易对方金额
     */
    public PeerAccountAmount setOrderId(long peerAccountId, String orderId) {
        PeerAccountAmount p = get(peerAccountId);
        p.setOrderId(orderId);
        return p;
    }

    /**
     * 删除指定交易对方账户id的金额设置
     * 
     * @param peerAccountId
     *            交易对方账户id
     * @return 被删除的交易对方金额
     */
    public PeerAccountAmount remove(long peerAccountId) {
        return (PeerAccountAmount) this.values.remove(getKey(peerAccountId));
    }
}
